import json
import logging
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from django.core.cache import cache
from django.db import transaction
from django.db.models import Q
from django.utils import timezone

# 导入必要的模型和序列化器
from merchants.models import *
from vouchers.models import *
from cashbonus.models import *

from equity_mall.utils.pages import MyPage
from equity_mall.utils.wash_level1 import ylx_api
from equity_admin.tasks import *

# 配置日志
logger = logging.getLogger(__name__)


class PushDetailsData(ModelViewSet):
    DISTRIBUTION_PLATFORM_CACHE_KEY = 'distribution_ids'
    DEFAULT_START_DATE = '2025-01-01 00:00:00'
    PROVIDENCE_ID = 7330
    CACHE_TIMEOUT = 3600  # 缓存1小时

    # 活动类型映射
    ACTIVITY_TYPES = {
        'ali_dai_jin_quan': {'channel': 1, 'type': '05', 'name': '支付宝代金券'},
        'weixin_dai_jin_quan': {'channel': 2, 'type': '05', 'name': '微信代金券'},
        'shang_jia_dai_jin_quan': {'channel': 3, 'type': '05', 'name': '商家代金券'},
        'action_ash_activity': {'type': '05', 'name': '微邮惠礼包'},
        'merchant_draw': {'type': '03', 'name': '商户达标奖励'},
    }

    # 渠道到活动类型的映射
    CHANNEL_TO_ACTIVITY = {
        1: 'ali_dai_jin_quan',
        2: 'weixin_dai_jin_quan',
        3: 'shang_jia_dai_jin_quan'
    }

    # 状态映射
    STATUS_MAPPING = {
        0: 'pending',
        1: 'normal',
        7: 'used',
        14: 'fail',
    }

    def push(self, request):
        """主推送方法，使用线程池并发处理多种活动类型"""
        data_futures = {}

        with ThreadPoolExecutor(max_workers=6) as executor:
            # 提交任务到线程池
            data_futures['ali_dai_jin_quan'] = executor.submit(
                self.process_coupon_activity, 1, AliDiscountCouponInfo,
                AliDiscountCouponInfoKeguan, 'alidiscountcouponinfo_id')

            data_futures['weixin_dai_jin_quan'] = executor.submit(
                self.process_coupon_activity, 2, AliDiscountCouponInfo,
                AliDiscountCouponInfoKeguan, 'alidiscountcouponinfo_id')

            data_futures['shang_jia_dai_jin_quan'] = executor.submit(
                self.process_coupon_activity, 3, AliDiscountCouponInfo,
                AliDiscountCouponInfoKeguan, 'alidiscountcouponinfo_id')

            # # 微邮惠礼包
            data_futures['action_ash_activity'] = executor.submit(
                self.process_cash_activity, CashActivityData,
                CashActivityDataKeguan, 'cashactivitydata_id')
            # # 商户达标奖励
            data_futures['merchant_draw'] = executor.submit(
                self.process_merchant_activity, MerchantEightEightDraw,
                MerchantEightEightDrawKeguan, 'draw_id')

        # 收集所有任务的结果
        results = {}
        for key, future in data_futures.items():
            try:
                results[key] = future.result()
            except Exception as e:
                logger.error(f"Error processing {key}: {str(e)}", exc_info=True)
                results[key] = {'error': str(e), 'status': 'failed'}

        return Response(results)

    def process_coupon_activity(self, coupon_channel, model_class, log_model, log_field):
        """处理支付宝、微信、商家券、美团代金券类活动领取明细-的通用方法"""
        today = timezone.now()
        distribution_ids = self.get_distribution_platform()

        queryset = model_class.objects.filter(
            alidiscountcoupon__publish_start_time__gte=self.DEFAULT_START_DATE,
            alidiscountcoupon__coupon_channel=coupon_channel,
            alidiscountcoupon__level__prov_id=self.PROVIDENCE_ID,
            status__in = [1,2,3,7,8,9,10,12]
        ).exclude(alidiscountcoupon__distribution_platform__id__in=distribution_ids)

        processed_count = 0
        success_count = 0
        failed_count = 0

        for item in queryset:
            is_exists = log_model.objects.filter(**{log_field: item.id}).exists()

            try:
                partake_time = item.gmt_distributed.strftime("%Y-%m-%dT%H:%M:%S.120+08:00")
                member_info = self.get_member_info(item)

                status = self.STATUS_MAPPING.get(item.status, 'unknown')

                # 根据渠道获取活动类型键
                activity_key = self.CHANNEL_TO_ACTIVITY.get(coupon_channel)
                if not activity_key:
                    logger.error(f"不支持的渠道类型: {coupon_channel}")
                    failed_count += 1
                    continue

                prize_data = {
                    "awardSeq": item.out_biz_no,
                    "awardType": self.ACTIVITY_TYPES[activity_key]['type'],
                    "status": status,
                    "awardName": item.alidiscountcoupon.activity_name,
                    "awardNum": int(item.alidiscountcoupon.amount * 100),
                    "stockId": item.alidiscountcoupon.template_id,
                    "couponId": item.voucher_id
                }

                if item.status in [1, 7]:
                    prize_data['receiveTime'] = item.gmt_create.strftime("%Y-%m-%dT%H:%M:%S.120+08:00")

                if item.status == 7:
                    prize_data['useTime'] = item.gmt_use.strftime("%Y-%m-%dT%H:%M:%S.120+08:00")

                body = self.build_request_body(
                    source_id=item.alidiscountcoupon.template_id,
                    log_id=item.out_biz_no,
                    member_info=member_info,
                    partake_time=partake_time,
                    prize_list=[prize_data]
                )

                # 发送数据到客管系统并记录日志
                success = self.send_to_keguan(body, log_model, {log_field: item.id}, today, is_exists=is_exists)
                processed_count += 1
                if success:
                    success_count += 1
                else:
                    failed_count += 1

            except KeyError as ke:
                logger.error(f"活动类型键不存在: {ke}，项目ID: {item.id}", exc_info=True)
                failed_count += 1
            except Exception as e:
                logger.error(f"处理项目 {item.id} 时出错: {str(e)}", exc_info=True)
                failed_count += 1

        return {
            'processed_count': processed_count,
            'success_count': success_count,
            'failed_count': failed_count,
            'status': 'success' if failed_count == 0 else 'partial_success'
        }

    def process_cash_activity(self, model_class, log_model, log_field):
        """处理微邮惠礼包活动领取明细"""
        today = timezone.now()
        queryset = model_class.objects.filter(
            cash_activity__available_begin_time__gte=self.DEFAULT_START_DATE,
            level__prov_id=self.PROVIDENCE_ID,
            status=2
        )

        processed_count = 0
        success_count = 0
        failed_count = 0

        for item in queryset:
            if log_model.objects.filter(**{log_field: item.id}).exists():
                continue

            try:
                activity = item.cash_activity
                received_time = item.received_time.strftime("%Y-%m-%dT%H:%M:%S.120+08:00")
                member_info = self.get_member_info(item, is_merchant=False, is_cash=True)

                body = self.build_request_body(
                    source_id=activity.activity_id,
                    log_id=item.payment_no,
                    member_info=member_info,
                    partake_time=received_time,
                    prize_list=[{
                        "awardSeq": item.payment_no,
                        "awardType": self.ACTIVITY_TYPES['action_ash_activity']['type'],
                        "status": "normal",
                        "awardName": activity.name,
                        "awardNum": int(item.amount * 100),
                        "receiveTime": received_time,
                    }]
                )

                success = self.send_to_keguan(body, log_model, {log_field: item.id}, today)
                processed_count += 1
                if success:
                    success_count += 1
                else:
                    failed_count += 1

            except Exception as e:
                logger.error(f"Error processing cash activity item {item.id}: {str(e)}", exc_info=True)
                failed_count += 1

        return {
            'processed_count': processed_count,
            'success_count': success_count,
            'failed_count': failed_count,
            'status': 'success' if failed_count == 0 else 'partial_success'
        }

    def process_merchant_activity(self, model_class, log_model, log_field):
        """处理商户达标奖励活动领取明细"""
        today = timezone.now()
        # 获取符合条件的活动ID
        activity_ids = MerchantEightEightActivity.objects.filter(
            activity_start_time__gte=self.DEFAULT_START_DATE,
            level__prov_id=self.PROVIDENCE_ID,
            status=2#领取状态为已领取
        ).values_list("id", flat=True)

        queryset = model_class.objects.filter(activity_id__in=activity_ids)

        processed_count = 0
        success_count = 0
        failed_count = 0

        for item in queryset:
            if log_model.objects.filter(**{log_field: item.id}).exists():
                continue

            try:
                activity = MerchantEightEightActivity.objects.filter(id=item.activity_id).first()
                if not activity:
                    logger.warning(f"Activity not found for draw ID: {item.id}")
                    failed_count += 1
                    continue

                received_time = item.received_time.strftime("%Y-%m-%dT%H:%M:%S.120+08:00")
                member_info = self.get_member_info(item, is_merchant=True)

                body = self.build_request_body(  # 修正方法名：build_request_bsody -> build_request_body
                    source_id=f'SHDB{str(activity.id).zfill(7)}',
                    log_id=item.payment_no,
                    member_info=member_info,
                    partake_time=received_time,
                    prize_list=[{
                        "awardSeq": item.payment_no,
                        "awardType": self.ACTIVITY_TYPES['merchant_draw']['type'],
                        "status": "normal",
                        "awardName": activity.activity_name,
                        "awardNum": int(item.amount * 100),
                        "receiveTime": received_time,
                    }]
                )

                success = self.send_to_keguan(body, log_model, {log_field: item.id}, today)
                processed_count += 1
                if success:
                    success_count += 1
                else:
                    failed_count += 1

            except Exception as e:
                logger.error(f"Error processing merchant activity item {item.id}: {str(e)}", exc_info=True)
                failed_count += 1

        return {
            'processed_count': processed_count,
            'success_count': success_count,
            'failed_count': failed_count,
            'status': 'success' if failed_count == 0 else 'partial_success'
        }

    def get_member_info(self, item, is_merchant=False, is_cash=False):
        """通用方法：获取会员信息"""
        if is_merchant:
            if hasattr(item, 'merchantuser_id') and item.merchantuser_id:
                member_id = item.merchantuser_id
                cstm_name = item.realname
                mobile_no = item.merchantuser.mobile if hasattr(item.merchantuser, 'mobile') else item.mobile
                id_card = item.merchantuser.identification_number if (
                        hasattr(item.merchantuser, 'identification_number') and
                        item.merchantuser.identification_number and
                        '**' not in item.merchantuser.identification_number
                ) else ''
            else:
                member_id = item.mobile
                cstm_name = item.realname
                mobile_no = item.mobile
                id_card = ''
        else:
            if is_cash:
                user_field = 'customeruservice' if hasattr(item,
                                                           'customeruservice_id') and item.customeruservice_id else 'customer_user'
            else:
                user_field = 'customeruservice' if hasattr(item,
                                                           'customeruservice_id') and item.customeruservice_id else 'customer_user'

            user = getattr(item, user_field)
            member_id = getattr(item, f'{user_field}_id')
            cstm_name = user.realname
            mobile_no = user.mobile

            id_card_field = 'idcode' if hasattr(user, 'idcode') else 'identification_number'
            id_card = getattr(user, id_card_field) if (
                    hasattr(user, id_card_field) and
                    getattr(user, id_card_field) and
                    '**' not in getattr(user, id_card_field)
            ) else ''

        return {
            'memberId': str(member_id),
            'cstmName': cstm_name,
            'mobileNo': mobile_no,
            'idCard': id_card
        }

    def build_request_body(self, source_id, log_id, member_info, partake_time, prize_list):
        """构建请求体的通用方法"""
        body = {
            'sourceId': source_id,
            'logId': log_id,
            'memberId': member_info['memberId'],
            'cstmName': member_info['cstmName'],
            'mobileNo': member_info['mobileNo'],
            'partakeTime': partake_time,
            'prizeList': prize_list
        }

        if member_info['idCard']:
            body['cardType'] = '10'
            body['idCard'] = member_info['idCard']

        return body

    def send_to_keguan(self, body, log_model, log_filter, today, is_exists):
        """
        发送数据到客管系统并记录日志，根据is_exists参数控制push_time更新策略
        - is_exists=True: 仅更新push_time为最新时间
        - is_exists=False: 正常新增或更新记录
        """
        from django.utils import timezone
        from django.db import close_old_connections
        today = timezone.now()
        log_action = "更新" if is_exists else "创建或更新"
        logger.info(f"准备{log_action}日志记录: {log_filter}")

        # 注释掉调试代码
        # print(body)
        # return JsonResponse({})

        try:
            keguan_result = ylx_api('ThirdActDataSyncGdCrm', body)

            # 构建统一的日志数据结构
            log_data = {
                'push_status': 1 if keguan_result['meta']['code'] == 200 else 2,
                'push_time': today,
                'api_response': json.dumps(keguan_result),
                'process_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
            if 'msg' in keguan_result['meta']:
                log_data['return_msg'] = keguan_result['meta']['msg']

            # 执行数据库操作
            if is_exists:
                update_count = log_model.objects.filter(**log_filter).update(**log_data)
                if update_count == 0:
                    logger.warning(f"{log_action}失败: 未找到记录 {log_filter}")
                    return False
                logger.info(f"成功{log_action}记录: {log_filter}")
            else:
                log_model.objects.update_or_create(defaults=log_data, **log_filter)
                logger.info(f"成功{log_action}新记录: {log_filter}")

            return keguan_result['meta']['code'] == 200

        except Exception as e:
            error_data = {
                'push_status': 2,
                'return_msg': str(e),
                'push_time': today,
                'error_detail': str(e),
                'error_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            }
            if is_exists:
                log_model.objects.filter(**log_filter).update(**error_data)
            else:
                log_model.objects.update_or_create(defaults=error_data, **log_filter)
            logger.error(f"{log_action}记录失败: {log_filter}, 错误: {str(e)}", exc_info=True)
            return False

        finally:
            close_old_connections()  # 释放数据库连接

    @classmethod
    def get_distribution_platform(cls):
        """找出去除对应的平台后的派发id"""
        distribution_ids = cache.get(cls.DISTRIBUTION_PLATFORM_CACHE_KEY)
        if distribution_ids is not None:
            return distribution_ids

        platform_names = ["微邮惠", "邮乐享", "(安徽)皖邮惠", "(江苏)江苏邮政微金融",
                          "(吉林)吉林邮政E权益", "(陕西)陕邮惠小程序", "(广西)邮储好礼汇"]
        ids = []

        for platform_name in platform_names:
            platform_ids = AliDiscountCouponDistributionPlatform.objects.filter(
                platform_name=platform_name
            ).values_list("id", flat=True)

            if platform_ids:
                ids.append(platform_ids[0])

        cache.set(cls.DISTRIBUTION_PLATFORM_CACHE_KEY, ids, cls.CACHE_TIMEOUT)
        return ids